package com.zhenyi.xiaohuoche.admin;

import java.io.File;
import java.util.Date;

import org.hashids.Hashids;
import org.joda.time.DateTime;

import com.cjw.model.DBMap;
import com.jfinal.aop.Before;
import com.jfinal.aop.Clear;
import com.jfinal.kit.HttpKit;
import com.jfinal.kit.JsonKit;
import com.jfinal.kit.LogKit;
import com.jfinal.kit.PropKit;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.tx.Tx;
import com.jfinal.plugin.redis.Cache;
import com.jfinal.plugin.redis.Redis;
import com.utils.DateUtils;
import com.utils.PathUtils;
import com.utils.image.UploadUtils;
import com.xhc.common.model.XhcEnroll;
import com.xhc.common.model.XhcUserTicket;
import com.zhenyi.xhc.core.XHCAuthInterceptor;
import com.zhenyi.xhc.core.XHCController;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.file.FileWriter;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;

@Before(XHCAuthInterceptor.class)
public class AdminApiController extends XHCController {
	private final Hashids piaoHashids = new Hashids("piao", 8);
	private final String TESTING_CODE = "8XyO5ew5";
	private final String XHC_TICKET_PREFIX = PropKit.get("XHC_TICKET_PREFIX", "Experience_");
	private final String XHC_TICKET_EXPIRES = PropKit.get("XHC_TICKET_EXPIRES", "2019-02-06 23:59:59");

	private FileWriter fileWriter = new FileWriter(PathUtils.getFile("logs", "xhcGate.txt"));

	@Clear
	public void check() {
		String ticketCode = getPara(0);
		checkTicket(ticketCode);
	}

	@Clear
	public void check2() {
		String ticketCode = getPara(0);
		ticketLeave(ticketCode);
	}

	@Clear
	@Override
	public void index() {
		super.index();
		// gateapi,gateapi
		String m = getPara("m");
		// gatealive,checkticket
		String a = getPara("a");
		if (!StrKit.notBlank(a, m)) {
			LogKit.warn("m or a is empty");
			renderFailure("m or a is empty");
			return;
		}
		if (!"gateapi".equals(m)) {
			LogKit.warn("m not eqauls gateapi");
			renderFailure("m not eqauls gateapi");
			return;
		}
		String body = HttpKit.readData(getRequest());
		if (StrKit.isBlank(body)) {
			LogKit.warn("body is blank");
			renderFailure("body is blank");
			return;
		}
		if ("-cancellation".equals(a)) {
			fileWriter.append(DateUtil.now() + "\n");
			fileWriter.append(body + "\n");
			/**
			 * 注销票接口
			 */
			try {
				JSONObject jsonObject = JSONUtil.parseObj(body);
				// 进出方向 in：入口 out：出口
				String inOutDirect = jsonObject.getStr("InOutDirect");
				// if (!"in".equals(inOutDirect)) {
				// LogKit.info("InOutDirect error");
				// renderCheckFail();
				// return;
				// }
				// 闸机通道号
				String gateNum = jsonObject.getStr("gateNum");
				// 票类rfid：IC卡qrcode：二维码
				String ticketType = jsonObject.getStr("ticketType");
				if (!"qrcode".equals(ticketType)) {
					LogKit.info("ticketType error");
					renderCheckFail();
					return;
				}
				// 票属性 normal：正常刷票 other：待定
				String ticketProperty = jsonObject.getStr("ticketProperty");
				if (!"normal".equals(ticketProperty)) {
					LogKit.info("ticketProperty error");
					renderCheckFail();
					return;
				}
				// 票号.
				String ticketCode = jsonObject.getStr("ticketCode");
				cancelTicket(ticketCode);
				return;
			} catch (Exception e) {
				LogKit.info("check error", e);
				renderCheckFail();
				return;
			}
		} else if ("checkticket".equals(a)) {
			fileWriter.append(DateUtil.now() + "\n");
			fileWriter.append(body + "\n");
			/**
			 * 验票接口
			 */
			try {
				// LogKit.info("body: " + body);
				JSONObject jsonObject = JSONUtil.parseObj(body);
				// 进出方向 in：入口 out：出口
				String inOutDirect = jsonObject.getStr("InOutDirect");
				boolean isIn = false;
				// boolean isOut = false;
				if ("in".equals(inOutDirect)) {
					// LogKit.info("InOutDirect error");
					// renderCheckFail();
					// return;
					isIn = true;
				}
				if ("out".equals(inOutDirect)) {
					// LogKit.info("InOutDirect error");
					// renderCheckFail();
					// return;
					isIn = false;
				}
				// 闸机通道号
				String gateNum = jsonObject.getStr("gateNum");
				if ("00003".equals(gateNum)) {
					isIn = false;
				}
				if ("00001".equals(gateNum)) {
					isIn = false;
				}
				// 票类rfid：IC卡qrcode：二维码
				String ticketType = jsonObject.getStr("ticketType");
				if (!"qrcode".equals(ticketType)) {
					LogKit.info("ticketType error");
					renderCheckFail();
					return;
				}
				// 票属性 normal：正常刷票 other：待定
				String ticketProperty = jsonObject.getStr("ticketProperty");
				if (!"normal".equals(ticketProperty)) {
					LogKit.info("ticketProperty error");
					renderCheckFail();
					return;
				}
				// 票号
				String ticketCode = jsonObject.getStr("ticketCode");
				fileWriter.append(ticketCode + " isIn:" + isIn + "\n");
				// System.out.println(ticketCode + " isIn:" + isIn);
				if (isIn) {
					checkTicket(ticketCode);
					return;
				} else {
					ticketLeave(ticketCode);
					renderCheck(1, 0, 8, "", "", "", "请过闸");
					return;
				}
			} catch (Exception e) {
				LogKit.info("check error", e);
				renderCheckFail();
				return;
			}
		} else if ("gatealive".equals(a)) {
			/**
			 * 闸机心跳接口（反馈闸机设备运行状态）
			 */
			try {
				JSONObject jsonObject = JSONUtil.parseObj(body);
				String gateNum = jsonObject.getStr("gateNum");
				String userName = jsonObject.getStr("userName");
				String password = jsonObject.getStr("password");
				String reserved = jsonObject.getStr("reserved");
				// LogKit.info("gateNum: " + gateNum);
				// LogKit.info("userName: " + userName);
				// LogKit.info("password: " + password);
				// LogKit.info("reserved: " + reserved);
				DBMap map = new DBMap();
				// 成功和失败状态（200-成功，201-失败）
				map.put("status", 200);
				map.put("errorMessage", "" + gateNum);
				// LogKit.info(gateNum + " heart beat");
				// LogKit.info(body);
				// LogKit.info(JsonKit.toJson(map));
				renderJson(map);
			} catch (Exception e) {
				LogKit.warn("heart beat error", e);
				renderFailure("heart beat error");
			}
		} else {
			fileWriter.append(DateUtil.now() + "\n");
			fileWriter.append(body + "\n");
			renderFailure("not such method");
		}
	}

	private void renderCheckFail() {
		renderCheck(0, 0, 14, "", "", "", "");
	}

	/**
	 * 
	 * @param result
	 * @param checkType
	 * @param voiceNum
	 * @param msg1
	 * @param msg2
	 * @param msg3
	 * @param msg4
	 */
	private void renderCheck(int result, Integer checkType, Integer voiceNum, String msg1, String msg2, String msg3,
			String msg4) {
		DBMap map = new DBMap();
		map.put("checkResult", result);
		map.put("checkType", checkType);
		map.put("VoiceNum", voiceNum);
		map.put("checkMsg1", msg1);
		map.put("checkMsg2", msg2);
		map.put("checkMsg3", msg3);
		map.put("checkMsg4", msg4);
		String json = JsonKit.toJson(map);
		fileWriter.append(json + "\n");
		renderJson(map);
	}

	private void cancelTicket(String code) {
		if (StrKit.isBlank(code)) {
			// renderFailure("code is blank");
			renderCheckFail();
			return;
		}
		Long id = null;
		try {
			id = piaoHashids.decode(code)[0];
		} catch (Exception e) {
			// renderFailure("code error");
			LogKit.warn("code error");
			renderCheckFail();
			return;
		}
		XhcUserTicket ticket = XhcUserTicket.dao.findById(id);
		if (ticket == null) {
			LogKit.warn("ticket not exist");
			renderCheckFail();
			return;
		}
		DBMap map = new DBMap();
		map.put("checkResult", "OK");
		if (TESTING_CODE.equals(code)) {
			LogKit.info("test cancel ticket");
			renderJson(map);
			return;
		}
		// ticket.setIsUsed(0);
		boolean flag = ticket.update();
		if (!flag) {
			LogKit.warn("ticket update fail");
			renderCheckFail();
			return;
		}
		renderJson(map);
	}

	private void ticketLeave(String code) {
		if (StrKit.isBlank(code)) {
			// renderFailure("code is blank");
			renderCheckFail();
			return;
		}
		Long id = null;
		try {
			id = piaoHashids.decode(code)[0];
		} catch (Exception e) {
			// renderFailure("code error");
			LogKit.warn("leave code error");
			renderCheckFail();
			return;
		}
		XhcUserTicket ticket = XhcUserTicket.dao.findById(id);
		if (ticket == null) {
			LogKit.warn("leave ticket not exist");
			renderCheckFail();
			return;
		}
		ticket.setOutTime(new Date());
		if (ticket.getInTime() != null) {
			long duration = ticket.getOutTime().getTime() - ticket.getInTime().getTime();
			duration = duration / 60000;
			ticket.setDuration(duration);
		}
		ticket.setIsUsed(ONE);
		ticket.update();
		renderCheck(1, 0, 8, "票类：普通票", "", "", "请过闸");
	}

	private void checkTicket(String code) {
		if (StrKit.isBlank(code)) {
			LogKit.warn("code is blank");
			renderCheckFail();
			return;
		}
		Cache cache = Redis.use();
		// LogKit.info("code: " + code);
		if (code.contains(XHC_TICKET_PREFIX)) {
			String checkCode = code.replace(XHC_TICKET_PREFIX, "");
			try {
				Long codeNo = piaoHashids.decode(checkCode)[0];
				// LogKit.info("check " + XHC_TICKET_PREFIX + " suc " + codeNo);
			} catch (Exception e) {
				renderCheckFail();
				return;
			}
			if (cache.get(code) != null) {
				renderCheckFail();
				return;
			}
			Date now = new Date();
			Date expires = DateUtil.parse(XHC_TICKET_EXPIRES, DateUtils.YYYYMMDD_HHMMSS);
			if (now.getTime() <= expires.getTime()) {
				cache.setex(code, 3600 * 24 * 30, code);
				renderCheck(1, 0, 7, "票类：内部票", "票号：" + code, "", "验票成功，请过闸");
				return;
			} else {
				renderCheckFail();
				return;
			}
		}
		if (code.contains("Invite_")) {
			if (!"2019-01-12".equals(DateUtil.today())) {
				renderCheckFail();
				return;
			}
			if (cache.get(code) != null) {
				renderCheckFail();
				return;
			}
			cache.setex(code, 3600 * 24, code);
			renderCheck(1, 0, 7, "票类：邀请票", "票号：" + code, "", "验票成功，请过闸");
			return;
		}
		if (TESTING_CODE.equals(code)) {
			renderCheck(1, 0, 7, "票类：普通票", "票号：", "测试票", "验票成功，请过闸");
			// LogKit.info("测试票 通过");
			return;
		}
		Long id = null;

		if (cache.get(code) != null) {
			try {
				Long userTicketId = cache.get(code);
				if (userTicketId == null) {
					renderCheckFail();
					return;
				}
				id = userTicketId;
			} catch (Exception e) {
				LogKit.warn(code + "get user ticket error", e);
			}
		}

		if (id == null) {
			try {
				id = piaoHashids.decode(code)[0];
			} catch (Exception e) {
				// renderFailure("code error");
				LogKit.warn("code error");
				renderCheckFail();
				return;
			}
		}
		XhcUserTicket ticket = XhcUserTicket.dao.findById(id);
		if (ticket == null) {
			LogKit.warn("ticket not exist");
			renderCheckFail();
			return;
		}
		if (!ONE.equals(ticket.getStatus())) {
			LogKit.warn("ticket refund");
			renderCheckFail();
			return;
		}
		if (ticket.getInTime() != null) {
			LogKit.warn("ticket is in");
			renderCheckFail();
			return;
		}
		if (ONE.equals(ticket.getIsUsed())) {
			LogKit.warn("ticket invalidate");
			renderCheckFail();
			return;
		}
		// LogKit.info("ticketTime: " + ticket.getTime() + " " + new Date());
		int beforeMin = PropKit.getInt("XHC_TICKET_CHECK_PRE", 0);
		if (new Date().getTime() < new DateTime(ticket.getTime()).minusMinutes(beforeMin).toDate().getTime()) {
			LogKit.warn("ticket invalidate 1");
			renderCheckFail();
			return;
		}
		int afterMin = PropKit.getInt("XHC_TICKET_CHECK_SUF", 60);
		if (new Date().getTime() > new DateTime(ticket.getTime()).plusMinutes(afterMin).toDate().getTime()) {
			LogKit.warn("ticket invalidate 2");
			renderCheckFail();
			return;
		}
		ticket.setInTime(new Date());
		// ticket.setIsUsed(1);
		boolean flag = ticket.update();
		if (!flag) {
			LogKit.warn("ticket update fail");
			renderCheckFail();
			return;
		}

		XhcEnroll enroll = new XhcEnroll();
		enroll.setAddTime();
		// enroll.setWechatId(getWechat().getId());
		enroll.setTicketId(ticket.getTicketId());
		enroll.setUserTicketId(ticket.getId());
		flag = enroll.save();
		if (!flag) {
			renderCheckFail();
			return;
		}
		// XhcOrder order = XhcOrder.dao.findById(ticket.getOrderId());
		// renderCheck(1, 0, 7, "票类：普通票", "票号：" + order.getOutTradeNo(), "",
		// "验票成功，请过闸");
		renderCheck(1, 0, 7, "票类：普通票", "", "", "验票成功，请过闸");

	}

	@Clear
	@Before(Tx.class)
	public void verify() {
		String code = getPara(0);
		if (StrKit.isBlank(code)) {
			renderFailure("code is blank");
			return;
		}
		Long id = null;
		try {
			id = piaoHashids.decode(code)[0];
		} catch (Exception e) {
			renderFailure("code error");
			return;
		}
		XhcUserTicket ticket = XhcUserTicket.dao.findById(id);
		if (ticket == null) {
			renderFailure("ticket not exist");
			return;
		}
		if (!ticket.getStatus().equals(1)) {
			renderFailure("ticket refund");
			return;
		}
		if (ticket.getIsUsed() != null) {
			renderFailure("ticket invalidate");
			return;
		}
		ticket.setIsUsed(1);
		boolean flag = ticket.update();
		if (flag) {
			XhcEnroll enroll = new XhcEnroll();
			enroll.setAddTime();
			enroll.setWechatId(getWechat().getId());
			enroll.setTicketId(ticket.getTicketId());
			enroll.setUserTicketId(ticket.getId());
			flag = enroll.save();
		}
		renderFlag(flag);
	}

	public void upload() {
		File file = getFileParam("file");
		if (file.length() > 0) {
			String url = UploadUtils.upload(file);
			renderSuccess(url);
		} else {
			renderFailure();
		}
	}
}

/*
 * 
 * String code = getPara(0); Hashids hashids = new Hashids("piao", 8); Long id =
 * hashids.decode(code)[0]; XhcUserTicket userTicket =
 * XhcUserTicket.dao.findById(id); if (userTicket.getIsUsed() != null &&
 * userTicket.getIsUsed().equals(1)) { renderFailure("ticket used"); return; }
 * userTicket.setIsUsed(1); userTicket.setUseTime(new Date()); //
 * userTicket.setStatus(1); boolean flag = userTicket.update(); if (flag) {
 * XhcEnroll enroll = new XhcEnroll(); enroll.setAddTime();
 * enroll.setWechatId(getWechat().getId());
 * enroll.setTicketId(userTicket.getTicketId()); flag = enroll.save(); }
 * renderFlag(flag);
 * 
 */
